#if (FEATURE_MODE == 0)
/**
 @file Ctc_npm_cli.c

 @date 2016-04-26

 @version v1.0

 This file defines functions for npm cli module

*/

#include "ctc_api.h"
#include "ctcs_api.h"
#include "ctc_cli.h"
#include "ctc_cli_common.h"
#include "ctc_debug.h"
#include "ctc_npm.h"
extern int32 ex_cplusplus_cm_oam_auto_gen_pkt_tx_pkt_trigger(uint32 chip_id, uint32 update_tick_times);

#define CTC_CLI_NPM_M_STR "NPM Module"

struct sample_thread_s
{
    uint8 ldev;
    uint32 session_id ;
    uint8 rsv[2];
    uint16 interval;
    uint16 num;
    sal_task_t* p_sample_task;
    ctc_vti_t* vty;
};
typedef struct sample_thread_s sample_thread_t;

struct sample_cache_s
{
    uint8  valid;
    uint32  session_id;
    uint16 interval;
    uint8  num;
    uint8  tx_en;
    uint16 local_count;
    double ir_local;
    uint64 fd_local;
    uint64 tx_pkts;
    uint64 rx_pkts;
};
typedef struct sample_cache_s sample_cache_t;

#define tx_rate         CTC_VTY_CLIENT(vty)->npm_tx_rate
#define g_ipg             CTC_VTY_CLIENT(vty)->npm_ipg
#define sample_cache    ((sample_cache_t*)CTC_VTY_CLIENT(vty)->npm_cache)
#define CTC_CLI_NPM_CAHCE_INIT(_rv_)  \
{\
    if (!CTC_VTY_CLIENT(vty)->npm_cache)\
    {\
        CTC_VTY_CLIENT(vty)->npm_cache = mem_malloc(MEM_CLI_MODULE, sizeof(sample_cache_t)*CTC_CONST256);\
        if (!CTC_VTY_CLIENT(vty)->npm_cache) { return _rv_; }\
        sal_memset(CTC_VTY_CLIENT(vty)->npm_cache, 0, sizeof(sample_cache_t)*CTC_CONST256);\
    }\
}

int32 ctc_npm_time_delay_transfer(uint64 time, uint64* time_s, uint64* time_ms, uint64* time_us, uint64* time_ns)
{
    *time_s = time / 1000000000;
    *time_ms = (time - ((*time_s) * 1000000000)) / 1000000;
    *time_us = (time - ((*time_s) * 1000000000) - ((*time_ms) * 1000000)) / 1000;
    *time_ns = time - (*time_s) * 1000000000 - (*time_ms) * 1000000 - (*time_us) * 1000;

    return CLI_SUCCESS;
}


CTC_CLI(ctc_cli_npm_set_session_transmit_en,
        ctc_cli_npm_set_session_transmit_en_cmd,
        "npm session SESSION transmit(enable | disable) (lite |)",
        CTC_CLI_NPM_M_STR,
        "Session id",
        "Value",
        "Transmit",
        CTC_CLI_ENABLE,
        CTC_CLI_DISABLE,
        "lite mode"
        )
{
    int32 ret = CLI_SUCCESS;
    uint8 enable = 0;
    uint32 session_id = 0;
    uint8 index = 0;

    CTC_CLI_GET_UINT32_RANGE("session id", session_id, argv[0], 0, CTC_MAX_UINT32_VALUE);
    index = CTC_CLI_GET_ARGC_INDEX("lite");
    if (index != 0xFF)
    {
        session_id |= (CTC_NPM_SESSION_TYPE_LITE<<CTC_NPM_SESSION_ID_LEN);
    }
    if (0 == sal_memcmp(argv[1], "enable", sal_strlen("enable")))
    {
        enable = 1;
    }
    else
    {
        enable = 0;
    }

    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_set_transmit_en(g_api_ldev,  session_id, enable);
    }
    else
    {
        ret = ctc_npm_set_transmit_en(g_api_ldev, session_id, enable);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s \n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}


#if defined(SDK_IN_USERMODE)
STATIC void
_npm_cli_sat_sample_thread(void* param)
{
    int32 ret = 0;
    uint16 loop = 0;
    uint64 ts_tmp = 0;
    uint64 last_ts_tmp = 0;
    uint64 last_rx_bytes = 0;
    uint64 last_rx_pkts = 0;
    uint64 last_tx_pkts = 0;
    uint64 delta_rx_pkts = 0;
    uint64 delta_rx_bytes = 0;
    uint64 delta_tx_pkts = 0;
    uint64 last_total_delay = 0;
    double ir_max = 0;
    double ir_min = 0;
    double ir_tmp = 0;
    uint64 fd_max = 0;
    uint64 fd_min = 0;
    uint64 fd_average = 0;
    uint64 fd_tmp = 0;
    uint8  count = 0;

    sample_thread_t* sample_thread = (sample_thread_t*)param;
    ctc_vti_t* vty = sample_thread->vty;
    ctc_npm_stats_t stats;
    sal_memset(&stats, 0, sizeof(ctc_npm_stats_t));
    CTC_CLI_NPM_CAHCE_INIT();

    for (loop = 0; loop < sample_thread->num + 1; loop++)
    {
        if (g_ctcs_api_en)
        {
            ret = ctcs_npm_get_stats(g_api_ldev,  sample_thread->session_id, &stats);
        }
        else
        {
            ret = ctc_npm_get_stats(sample_thread->ldev, sample_thread->session_id, &stats);
        }
        if (ret < 0)
        {
            ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        }

        if (0 == loop)
        {
            last_ts_tmp = stats.last_ts;
            last_rx_bytes = stats.rx_bytes;
            last_rx_pkts = stats.rx_pkts;
            last_tx_pkts = stats.tx_pkts;
            last_total_delay = stats.total_delay;
            sal_task_sleep(sample_thread->interval);
            continue;
        }

        /*IR during curent interval :bps*/
        ts_tmp = (stats.last_ts >= last_ts_tmp )?(stats.last_ts - last_ts_tmp):(stats.last_ts + (0xFFFFFFFFFFFFFFFFLLU - last_ts_tmp));
        if((stats.rx_bytes >= last_rx_bytes) && (stats.rx_pkts > last_rx_pkts))
        {
            delta_rx_bytes = stats.rx_bytes - last_rx_bytes;
            ir_tmp = (delta_rx_bytes + (stats.rx_pkts - last_rx_pkts)* g_ipg[sample_thread->session_id]) * 8 / (double)ts_tmp *1000000000;
        }

        ir_max = (ir_tmp > ir_max)?ir_tmp:ir_max;
        ir_min = (1 == loop)? ir_tmp:ir_min;
        ir_min = (ir_min < ir_tmp)?ir_min:ir_tmp;

        /*FD, ns per PDU*/
        if ((stats.rx_pkts>= last_rx_pkts)&& (stats.total_delay >= last_total_delay))
        {
            fd_tmp = (stats.rx_pkts - last_rx_pkts) ? (stats.total_delay - last_total_delay) / (stats.rx_pkts- last_rx_pkts) : 0;
        }
        fd_max = (fd_tmp > fd_max)?fd_tmp:fd_max;
        fd_min = (1 == loop)? fd_tmp:fd_min;
        fd_min = (fd_min < fd_tmp)?fd_min:fd_tmp;

        fd_average = stats.rx_pkts ? (stats.total_delay) / stats.rx_pkts : 0;

        if ((stats.rx_pkts >= last_rx_pkts)&& (stats.tx_pkts >= last_tx_pkts))
        {
            delta_rx_pkts = stats.rx_pkts - last_rx_pkts;
            delta_tx_pkts = stats.tx_pkts - last_tx_pkts;
        }

        /*update*/
        last_ts_tmp = stats.last_ts;
        last_rx_bytes = stats.rx_bytes;
        last_rx_pkts = stats.rx_pkts;
        last_tx_pkts = stats.tx_pkts;
        last_total_delay = stats.total_delay;


        /*add to sample_cache*/
        sample_cache[count].valid = 1;
        sample_cache[count].fd_local = fd_tmp;
        sample_cache[count].ir_local = ir_tmp;
        sample_cache[count].tx_pkts = delta_tx_pkts;
        sample_cache[count].rx_pkts = delta_rx_pkts;
        sample_cache[count].session_id = sample_thread->session_id;
        sample_cache[count].interval = sample_thread->interval;
        sample_cache[count].num = sample_thread->num;
        sample_cache[count].tx_en = stats.tx_en;
        sample_cache[count].local_count = loop;
        if (255 == count)
        {
            count = 0;
        }
        else
        {
            count++;
        }

        sal_task_sleep(sample_thread->interval);
    }

    ctc_cli_out("-------------------------Session %u SAT Report-------------------------\n",sample_thread->session_id);
    ctc_cli_out("IR:Information Rate    FTD:Frame Transfer Delay    FL:Frame Loss \n");
    ctc_cli_out("-----------------------------------------------------------------------\n");
    ctc_cli_out("%-30s: %d\n", "Interval(ms)", sample_thread->interval);
    ctc_cli_out("%-30s: %d\n", "Sample num", sample_thread->num);
    if (ir_max > 1000*1000)
    {
        ctc_cli_out("%-30s: %.2lf\n", "Rx-rate Max(Mbps)", ir_max / 1000 / 1000);
    }
    else if(ir_max > 1000)
    {
        ctc_cli_out("%-30s: %.2lf\n", "Rx-rate Max(Kbps)", ir_max / 1000);
    }
    else
    {
        ctc_cli_out("%-30s: %.2lf\n", "Rx-rate Max(bps)", ir_max);
    }

    if (ir_min > 1000*1000)
    {
        ctc_cli_out("%-30s: %.2lf\n", "Rx-rate Min(Mbps)", ir_min / 1000 / 1000);
    }
    else if(ir_min > 1000)
    {
        ctc_cli_out("%-30s: %.2lf\n", "Rx-rate Min(Kbps)", ir_min / 1000);
    }
    else
    {
        ctc_cli_out("%-30s: %.2lf\n", "Rx-rate Min(bps)", ir_min);
    }

    ctc_cli_out("%-30s: %"PRIu64"\n", "FTD Max(ns)", fd_max);
    ctc_cli_out("%-30s: %"PRIu64"\n", "FTD Min(ns)", fd_min);
    ctc_cli_out("%-30s: %"PRIu64"\n", "FTD Average(ns)", fd_average);
    ctc_cli_out("%-30s: %s\n", "Transmit pkts enable", stats.tx_en?"Y":"N");
}



CTC_CLI(ctc_cli_npm_show_session_stats,
        ctc_cli_npm_show_session_stats_cmd,
        "show npm session SESSION stats (eth-slm | eth-dmm | eth-lbm | eth-1sl | eth-1dm | eth-tst | flex)\
        (sample-enable INTERVAL NUM|)(lite |)(clear-en |)",
        CTC_CLI_SHOW_STR,
        CTC_CLI_NPM_M_STR,
        "Session id",
        "Value",
        "Stats",
        "SLM",
        "DMM",
        "LBM",
        "1SL",
        "1DM",
        "TST",
        "Flexible packet(OWAMP/TWAMP,FLPDU,UDP ECHO,etc.)",
        "Sample enable",
        "Sample interval ",
        "Sample number ",
        "Lite mode",
        "Enable clear stats"
        )
{
    int32 ret = CLI_SUCCESS;
    uint32 session_id = 0;
    uint8 index = 0;
    ctc_npm_stats_t stats;
    uint64 time_s = 0;
    uint64 time_ms = 0;
    uint64 time_us = 0;
    uint64 time_ns = 0;
    uint64 duration_ts = 0;
    uint64 fl = 0;
    uint16 interval = 0;
    uint8  num = 0;
    double fl_ratio = 0;
    char first_ts[64] = {0};
    char last_ts[64] = {0};
    uint8 lite_mode=0;
    sal_time_t tv;
    sal_time_t tv1;
    sample_thread_t* sample_thread;

    sal_memset(&stats, 0, sizeof(ctc_npm_stats_t));
    sample_thread = mem_malloc(MEM_CLI_MODULE, sizeof(sample_thread_t));
    if (!sample_thread)
    {
        return CLI_ERROR;
    }
    sal_memset(sample_thread, 0, sizeof(sample_thread_t));

    CTC_CLI_GET_UINT32_RANGE("session id", session_id, argv[0], 0, CTC_MAX_UINT32_VALUE);
    index = CTC_CLI_GET_ARGC_INDEX("lite");
    if (index != 0xFF)
    {
        if (session_id >= CTC_NPM_LITE_SESSION_NUM)
        {
            ctc_cli_out("Invalid npm lite session id\n");
            mem_free(sample_thread);
            return CLI_ERROR;
        }
        session_id |= (CTC_NPM_SESSION_TYPE_LITE<<CTC_NPM_SESSION_ID_LEN);
        lite_mode=1;
    }
    index = CTC_CLI_GET_ARGC_INDEX("clear-en");
    if (index != 0xFF)
    {
        stats.clear_en = 1;
    }

    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_get_stats(g_api_ldev,  session_id, &stats);
    }
    else
    {
        ret = ctc_npm_get_stats(g_api_ldev, session_id, &stats);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    if (lite_mode)
    {
        session_id &=0x1FF;
    }
    index = CTC_CLI_GET_ARGC_INDEX("eth-slm");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for SLM-------------------------\n", session_id);
        ctc_npm_time_delay_transfer(stats.total_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total delay", time_s, time_ms, time_us, time_ns);
        ctc_npm_time_delay_transfer(stats.total_far_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total far delay", time_s, time_ms, time_us, time_ns);
        ctc_npm_time_delay_transfer(stats.total_near_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total near delay", time_s, time_ms, time_us, time_ns);

        ctc_cli_out("%-30s: %"PRIu64"\n", "Tx Fcf", stats.tx_fcf);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Tx Fcb", stats.tx_fcb);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Rx Fcl", stats.rx_fcl);
        /*average delay*/
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total delay average(ns)", stats.rx_pkts ? stats.total_delay/stats.rx_pkts : 0);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total far delay average(ns)", stats.rx_pkts ? stats.total_far_delay/stats.rx_pkts : 0);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total near delay average(ns)", stats.rx_pkts ? stats.total_near_delay/stats.rx_pkts : 0);

    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-1sl");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for 1SL-------------------------\n", session_id);
        ctc_npm_time_delay_transfer(stats.total_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total delay", time_s, time_ms, time_us, time_ns);

        /*need seq-en to cal tx_fcf*/
        ctc_cli_out("%-30s: %"PRIu64"\n", "Tx Fcf", stats.tx_fcf);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Rx Fcl", stats.rx_fcl);
        /*average delay*/
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total delay average(ns)", stats.rx_pkts ? stats.total_delay/stats.rx_pkts : 0);

    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-lbm");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for LBM-------------------------\n", session_id);
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-dmm");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for DMM-------------------------\n", session_id);
        ctc_npm_time_delay_transfer(stats.total_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total delay", time_s, time_ms, time_us, time_ns);
        ctc_npm_time_delay_transfer(stats.total_far_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total far delay", time_s, time_ms, time_us, time_ns);
        ctc_npm_time_delay_transfer(stats.total_near_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total near delay", time_s, time_ms, time_us, time_ns);

        /*average delay per PDU*/
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total delay average(ns)", stats.rx_pkts ? stats.total_delay / stats.rx_pkts : 0);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total far delay average(ns)", stats.rx_pkts ? stats.total_far_delay/stats.rx_pkts : 0);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total near delay average(ns)", stats.rx_pkts ? stats.total_near_delay / stats.rx_pkts : 0);

    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-1dm");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for 1DM-------------------------\n", session_id);
        ctc_npm_time_delay_transfer(stats.total_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total delay", time_s, time_ms, time_us, time_ns);

        ctc_cli_out("%-30s: %"PRIu64"\n", "Total delay average(ns)", stats.rx_pkts ? stats.total_delay / stats.rx_pkts : 0);
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-tst");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for TST-------------------------\n", session_id);
        ctc_npm_time_delay_transfer(stats.total_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total delay", time_s, time_ms, time_us, time_ns);

        ctc_cli_out("%-30s: %"PRIu64"\n", "Total delay average(ns)", stats.rx_pkts ? stats.total_delay / stats.rx_pkts : 0);

    }

    index = CTC_CLI_GET_ARGC_INDEX("flex");
    if (0xFF != index)
    {
        ctc_cli_out("-------------------------Session %u stats for FLEX-------------------------\n", session_id);
        ctc_npm_time_delay_transfer(stats.total_delay, &time_s, &time_ms, &time_us, &time_ns);
        ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Total delay", time_s, time_ms, time_us, time_ns);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total delay average(ns)", stats.rx_pkts ? stats.total_delay / stats.rx_pkts : 0);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total far delay average(ns)", stats.rx_pkts ? stats.total_far_delay / stats.rx_pkts : 0);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total near delay average(ns)", stats.rx_pkts ? stats.total_near_delay / stats.rx_pkts : 0);

    }
    /*duration*/
    tv = stats.first_ts /1000000000;
    tv1 = stats.last_ts /1000000000;
    sal_strncpy(first_ts, sal_ctime(&tv), sal_strlen(sal_ctime(&tv))-1);
    sal_strncpy(last_ts, sal_ctime(&tv1), sal_strlen(sal_ctime(&tv1))-1);
    ctc_cli_out("%-30s: [%s]\n", "First timestamp", first_ts);
    ctc_cli_out("%-30s: [%s]\n", "Last timestamp", last_ts);
    duration_ts = (stats.last_ts >= stats.first_ts)?(stats.last_ts - stats.first_ts):0;
    ctc_npm_time_delay_transfer(duration_ts, &time_s, &time_ms, &time_us, &time_ns);
    ctc_cli_out("%-30s: %"PRIu64"s : %"PRIu64"ms : %"PRIu64"us : %"PRIu64"ns\n", "Time of duration", time_s, time_ms, time_us, time_ns);

    /*FL*/
    ctc_cli_out("%-30s: %"PRIu64"\n", "Tx packets", stats.tx_pkts);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Rx packets", stats.rx_pkts);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Tx bytes", stats.tx_bytes);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Rx bytes", stats.rx_bytes);
    if (0 == stats.tx_en)
    {
        if (stats.tx_pkts >= stats.rx_pkts)
        {
            fl = stats.tx_pkts - stats.rx_pkts;
            fl_ratio = fl? ((double)fl / stats.tx_pkts):0;
        }
        ctc_cli_out("%-30s: %"PRIu64"\n", "Frame lost", fl);
        ctc_cli_out("%-30s: %.4lf%%\n", "Frame lost ratio", fl_ratio * 100);
    }
    ctc_cli_out("%-30s: %"PRIu64"\n", "Max delay", stats.max_delay);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Min delay", stats.min_delay);
    ctc_cli_out("%-30s: %u\n", "Max jitter", stats.max_jitter);
    ctc_cli_out("%-30s: %u\n", "Min jitter", stats.min_jitter);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Total jitter", stats.total_jitter);

    ctc_cli_out("%-30s: %u\n", "Two way max jitter", stats.max_jitter);
    ctc_cli_out("%-30s: %u\n", "Two way min jitter", stats.min_jitter);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Two way total jitter", stats.total_jitter);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Far max jitter", stats.far_end_jitter[0]);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Far min jitter", stats.far_end_jitter[1]);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Far total jitter", stats.far_end_jitter[2]);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Near max jitter", stats.near_end_jitter[0]);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Near min jitter", stats.near_end_jitter[1]);
    ctc_cli_out("%-30s: %"PRIu64"\n", "Near total jitter", stats.near_end_jitter[2]);
    ctc_cli_out("%-30s: %s\n", "Transmit pkts enable", stats.tx_en? "Y" : "N");
    ctc_cli_out("%-30s: %"PRIu64"\n", "Sequence disorder", stats.disorder_pkts);
    if (!lite_mode)
    {
        ctc_cli_out("%-30s: %"PRIu64"\n", "Max IR", stats.ir[0]);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Min IR", stats.ir[1]);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total SES count", stats.ses_cnt[0]);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total non-SES count", stats.ses_cnt[1]);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Seconds count", stats.seconds);
        ctc_cli_out("%-30s: %s\n", "In available period", stats.in_avl_period? "Y" : "N");
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total avaible period", stats.avl_periods[0]);
        ctc_cli_out("%-30s: %"PRIu64"\n", "Total unavaible period", stats.avl_periods[1]);
    }
    index = CTC_CLI_GET_ARGC_INDEX("sample-enable");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT16_RANGE("interval", interval, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        CTC_CLI_GET_UINT8_RANGE("num", num, argv[index + 2], 0, CTC_MAX_UINT8_VALUE);
        if (!interval || interval > 1023)
        {
            ctc_cli_out("ERROR: Interval value must be <1-1023>\n");
            mem_free(sample_thread);
            return CLI_ERROR;
        }

        if (!num)
        {
            ctc_cli_out("ERROR: NUM must must be <1-255>\n");
            mem_free(sample_thread);
            return CLI_ERROR;
        }
        if (!lite_mode)
        {
            sample_thread->ldev = g_api_ldev;
            sample_thread->interval = interval;
            sample_thread->num = num;
            sample_thread->session_id = session_id;
            sample_thread->vty = vty;

            ret = sal_task_create(&sample_thread->p_sample_task, "sample thread",
                                  SAL_DEF_TASK_STACK_SIZE, SAL_TASK_PRIO_DEF, _npm_cli_sat_sample_thread, (void*)sample_thread);
        }
        if (ret < 0)
        {
            ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
            mem_free(sample_thread);
            return CLI_ERROR;
        }
    }
    mem_free(sample_thread);
    return CLI_SUCCESS;
}
#endif

CTC_CLI(ctc_cli_npm_clear_session_stats,
        ctc_cli_npm_clear_session_stats_cmd,
        "npm clear stats session SESSION (lite |)",
        CTC_CLI_NPM_M_STR,
        "Clear",
        "Stats",
        "Session id",
        "Value",
        "Lite mode"
        )
{
    int32 ret = CLI_SUCCESS;
    uint32 session_id = 0;
    uint8 index = 0;

    CTC_CLI_GET_UINT32_RANGE("session id", session_id, argv[0], 0, CTC_MAX_UINT32_VALUE);
    index = CTC_CLI_GET_ARGC_INDEX("lite");
    if (index != 0xFF)
    {
        session_id |= (CTC_NPM_SESSION_TYPE_LITE<<CTC_NPM_SESSION_ID_LEN);
    }

    if(g_ctcs_api_en)
    {
        ret = ctcs_npm_clear_stats(g_api_ldev, session_id);
    }
    else
    {
        ret = ctc_npm_clear_stats(g_api_ldev, session_id);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_npm_set_global_cfg,
        ctc_cli_npm_set_global_cfg_cmd,
        "npm global-cfg {session-mode (max-session-number-8 | max-session-number-6 | max-session-number-4 | mode-0 | mode-1) | frame-size-array SIZE1 SIZE2 SIZE3 SIZE4 SIZE5 SIZE6 SIZE7 SIZE8 SIZE9 SIZE10 SIZE11 SIZE12 SIZE13 SIZE14 SIZE15 SIZE16}",
        CTC_CLI_NPM_M_STR,
        "Global config",
        "Session mode",
        "Max session number 8",
        "Max session number 6",
        "Max session number 4",
        "Max session number 32",
        "Max session number 16",
        "Frame size array",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value"
        )
{
    int32 ret = 0;
    uint8 index = 0;
    uint8 i = 0;

    ctc_npm_global_cfg_t npm;

    sal_memset(&npm, 0, sizeof(ctc_npm_global_cfg_t));

    if(g_ctcs_api_en)
    {
        ret = ctcs_npm_get_global_config(g_api_ldev, &npm);
    }
    else
    {
        ret = ctc_npm_get_global_config(g_api_ldev, &npm);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    index = CTC_CLI_GET_ARGC_INDEX("max-session-number-8");
    if (0xFF != index)
    {
        npm.session_mode = CTC_NPM_SESSION_MODE_8;
    }

    index = CTC_CLI_GET_ARGC_INDEX("max-session-number-6");
    if (0xFF != index)
    {
        npm.session_mode = CTC_NPM_SESSION_MODE_6;
    }

    index = CTC_CLI_GET_ARGC_INDEX("max-session-number-4");
    if (0xFF != index)
    {
        npm.session_mode = CTC_NPM_SESSION_MODE_4;
    }

    index = CTC_CLI_GET_ARGC_INDEX("mode-0");
    if (0xFF != index)
    {
        npm.session_mode = CTC_NPM_SESSION_MODE_32;
    }

    index = CTC_CLI_GET_ARGC_INDEX("mode-1");
    if (0xFF != index)
    {
        npm.session_mode = CTC_NPM_SESSION_MODE_16;
    }
    index = CTC_CLI_GET_ARGC_INDEX("frame-size-array");
    if (0xFF != index)
    {
        for (i = 0; i < CTC_NPM_MAX_EMIX_NUM; i++)
        {
            CTC_CLI_GET_UINT16_RANGE("frame size value", npm.emix_size[i], argv[index + 1 + i], 0, CTC_MAX_UINT16_VALUE);
        }
    }

    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_set_global_config(g_api_ldev, &npm);
    }
    else
    {
        ret = ctc_npm_set_global_config(g_api_ldev, &npm);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_npm_debug_on,
        ctc_cli_npm_debug_on_cmd,
        "debug npm (ctc|sys) (debug-level {func|param|info|error} |)",
        CTC_CLI_DEBUG_STR,
        "NPM module",
        "CTC layer",
        "Sys layer",
        CTC_CLI_DEBUG_LEVEL_STR,
        CTC_CLI_DEBUG_LEVEL_FUNC,
        CTC_CLI_DEBUG_LEVEL_PARAM,
        CTC_CLI_DEBUG_LEVEL_INFO,
        CTC_CLI_DEBUG_LEVEL_ERROR)
{

    uint32 typeenum = 0;
    uint8 level = CTC_DEBUG_LEVEL_INFO | CTC_DEBUG_LEVEL_FUNC | CTC_DEBUG_LEVEL_PARAM | CTC_DEBUG_LEVEL_ERROR;
    uint8 index = 0;

    index = CTC_CLI_GET_ARGC_INDEX("debug-level");
    if (index != 0xFF)
    {
        level = CTC_DEBUG_LEVEL_NONE;
        index = CTC_CLI_GET_ARGC_INDEX("func");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_FUNC;
        }

        index = CTC_CLI_GET_ARGC_INDEX("param");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_PARAM;
        }

        index = CTC_CLI_GET_ARGC_INDEX("info");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_INFO;
        }

        index = CTC_CLI_GET_ARGC_INDEX("error");
        if (index != 0xFF)
        {
            level |= CTC_DEBUG_LEVEL_ERROR;
        }
    }

    if (0 == sal_memcmp(argv[0], "ctc", 3))
    {
        typeenum = NPM_CTC;

    }
    else
    {
        typeenum = NPM_SYS;

    }

    ctc_debug_set_flag("npm", "npm", typeenum, level, TRUE);
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_npm_debug_off,
        ctc_cli_npm_debug_off_cmd,
        "no debug npm (ctc | sys)",
        CTC_CLI_NO_STR,
        CTC_CLI_DEBUG_STR,
        "NPM Module",
        "Ctc layer",
        "Sys layer")
{
    uint32 typeenum = 0;
    uint8 level = 0;

    if (0 == sal_memcmp(argv[0], "ctc", 3))
    {
        typeenum = NPM_CTC;
    }
    else if (0 == sal_memcmp(argv[0], "sys", 3))
    {
        typeenum = NPM_SYS;
    }

    ctc_debug_set_flag("npm", "npm", typeenum, level, FALSE);

    return CLI_SUCCESS;
}



CTC_CLI(ctc_cli_npm_show_global_cfg,
        ctc_cli_npm_show_global_cfg_cmd,
        "show npm global-cfg",
        CTC_CLI_SHOW_STR,
        CTC_CLI_NPM_M_STR,
        "Global config"
        )

{
    int32 ret = 0;
    uint8 i = 0;
    ctc_npm_global_cfg_t npm;

    sal_memset(&npm, 0, sizeof(ctc_npm_global_cfg_t));

    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_get_global_config(g_api_ldev, &npm);
    }
    else
    {
        ret = ctc_npm_get_global_config(g_api_ldev, &npm);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
#if defined(TSINGMA_MX) || defined(TSINGMA_GX) || defined(ARCTIC)
    if (0 == npm.session_mode)
    {
        ctc_cli_out("Max Session Number 32\n");
    }
    if (1 == npm.session_mode)
    {
        ctc_cli_out("Max Session Number 16\n");
    }
#else

    if (0 == npm.session_mode)
    {
        ctc_cli_out("Max Session Number 8\n");
    }
    if (1 == npm.session_mode)
    {
        ctc_cli_out("Max Session Number 6\n");
    }
    if (2 == npm.session_mode)
    {
        ctc_cli_out("Max Session Number 4\n");
    }
#endif
    ctc_cli_out("The EMIX Size Array is:\n");
    for (i = 0; i < CTC_NPM_MAX_EMIX_NUM; i++)
    {
        if (npm.emix_size[i] != 0)
        {
            ctc_cli_out("%d     ", npm.emix_size[i]);
        }
    }
    ctc_cli_out("\n");
    return CLI_SUCCESS;

}




#define CTC_NPM_MAX_PKTHDR_LEN 384

#if defined(SDK_IN_USERMODE)

uint32 _npm_cli_pkt_file_2_str(char *packet_buf, sal_file_t pfile_r)
{
    char     tmp_buff[128] = "";
    int32    tmp_buff_idx  = 0;
    int32    tmp_buff_tok_idx  = 0;
    int32    packet_buf_len = CTC_NPM_MAX_PKTHDR_LEN;

    while(sal_fgets(tmp_buff,sizeof(tmp_buff),pfile_r))
    {
        tmp_buff_idx = 0;
        while(tmp_buff[tmp_buff_idx] != '\0')
        {
            if((tmp_buff[tmp_buff_idx] == ' ')
                ||(tmp_buff[tmp_buff_idx] == '\n')
                ||(tmp_buff[tmp_buff_idx] == '\r')
                ||(tmp_buff[tmp_buff_idx] == '\t'))
            {
                tmp_buff_idx++;
                continue;
            }

            if(tmp_buff_tok_idx >= packet_buf_len)
            {
                goto out;
            }

            packet_buf[tmp_buff_tok_idx] = tmp_buff[tmp_buff_idx];
            tmp_buff_tok_idx++;
            tmp_buff_idx++;
        }
        sal_memset(tmp_buff,0,sizeof(tmp_buff));
    }

    out:
    return tmp_buff_tok_idx;
}

int32 _npm_cli_pkt_file_str_2_hex(char *dest_buf_hex, uint32 src_buf_len ,char *src_buf_str)
{
    int32      tmp_buff_tok_idx = 0;
    uint8    er_tmp  = 0;
    uint8    er_tmp1 = 0;


    while(src_buf_str[tmp_buff_tok_idx] != '\0')
    {
        if (tmp_buff_tok_idx  >= src_buf_len)
        {
            return  CTC_E_NONE;
        }
        if (src_buf_str[tmp_buff_tok_idx] >= '0' && src_buf_str[tmp_buff_tok_idx] <= '9')
        {
            er_tmp = src_buf_str[tmp_buff_tok_idx] - '0';
        }
        else if(src_buf_str[tmp_buff_tok_idx] >= 'A' && src_buf_str[tmp_buff_tok_idx] <= 'F')
        {
            er_tmp = src_buf_str[tmp_buff_tok_idx] - 'A' + 10;
        }
        else if(src_buf_str[tmp_buff_tok_idx] >= 'a' && src_buf_str[tmp_buff_tok_idx] <= 'f')
        {
            er_tmp = src_buf_str[tmp_buff_tok_idx] - 'a' + 10;
        }


        if (tmp_buff_tok_idx + 1 >= src_buf_len)
        {
            return  CTC_E_NONE;
        }
        if(src_buf_str[tmp_buff_tok_idx+1] >= '0' && src_buf_str[tmp_buff_tok_idx+1] <= '9')
        {
            er_tmp1 = src_buf_str[tmp_buff_tok_idx+1] - '0';
        }
        else if(src_buf_str[tmp_buff_tok_idx+1] >= 'A' && src_buf_str[tmp_buff_tok_idx+1] <= 'F')
        {
            er_tmp1 = src_buf_str[tmp_buff_tok_idx+1] - 'A' + 10;
        }
        else if(src_buf_str[tmp_buff_tok_idx+1] >= 'a' && src_buf_str[tmp_buff_tok_idx+1] <= 'f')
        {
            er_tmp1 = src_buf_str[tmp_buff_tok_idx+1] - 'a' + 10;
        }

        dest_buf_hex[tmp_buff_tok_idx/2] = er_tmp << 4 | er_tmp1;

        tmp_buff_tok_idx += 2;
    }

    return CTC_E_NONE;
}

int32
_npm_cli_packet_get_from_file(ctc_vti_t* vty, char* file, uint8* dest_buf_hex, uint32* pkt_len)
{
    uint8* pkt_buf_str = NULL;
    sal_file_t  pfile_r = NULL;
    pkt_buf_str = (uint8*)mem_malloc(MEM_CLI_MODULE, CTC_NPM_MAX_PKTHDR_LEN);
    if (NULL == pkt_buf_str)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(pkt_buf_str, 0 , CTC_NPM_MAX_PKTHDR_LEN);

    pfile_r = sal_fopen(file, "r");
    if(NULL == pfile_r)
    {
        ctc_cli_out("%% Failed to open the file <%s>\n", file);
        return CLI_ERROR;
    }

    *pkt_len = _npm_cli_pkt_file_2_str((char*)pkt_buf_str, pfile_r);
    sal_fclose(pfile_r);
    pfile_r = NULL;
    _npm_cli_pkt_file_str_2_hex((char*)dest_buf_hex, *pkt_len, (char*)pkt_buf_str);

    *pkt_len = *pkt_len/2 + *pkt_len % 2;

    if (pkt_buf_str)
    {
        mem_free(pkt_buf_str);
    }
    return CTC_E_NONE;
}


CTC_CLI(ctc_cli_npm_set_cfg,
        ctc_cli_npm_set_cfg_cmd,
        "npm session SESSION cfg (dest-gport GPORT| nh-id NHID )(is-mcast|)(pkt-sample (eth-lbm | eth-tst | eth-slm | eth-1sl | eth-dmm | eth-1dm) | pkt-file FILENAME) \
        frame-size-mode (fixed FRAME_SIZE | increased MIN_FRAME_SIZE MAX_FRAME_SIZE | emixed SIZE1 SIZE2 SIZE3 SIZE4 SIZE5 SIZE6 SIZE7 SIZE8 SIZE9 SIZE10 SIZE11 SIZE12 SIZE13 SIZE14 SIZE15 SIZE16) \
        rate RATE {vlan-id VLAN | cvlan-domain | tx-mode (continuous | pkt-num NUM | tx-period PERIOD) | patter-type (repeat REPEAT_VALUE | random | increase-by-byte | decrease-by-byte | increase-by-word | decrease-by-word) | \
        timeout TIME | burst-en BURSTCNT (ibg IBG_VALUE | ) | ts-en TSOFFSET(tunnel-pkt|) | seq-en SEQOFFSET | chksum-offset CHKSUMOFFSET| ipg IPG_VALUE | iloop (vrf-id VRF_ID|)| dm-stats-mode (far|near)|is-ntp-ts|light-mode-en |ses-thrd THRD|con-period PERIOD|}(color COLOR|)(priority PRIORITY|)(oam-type OAMTYPE|)",
        CTC_CLI_NPM_M_STR,
        "Session id",
        "Value",
        "Config",
        "Destination global port",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Nexthop id",
        "Nexthop id value",
        "Is dest group id",
        "Sample packet",
        "LBM",
        "TST",
        "SLM",
        "1SL",
        "DMM",
        "1DM",
        "File store packet",
        "File name",
        "Frame size mode",
        "Fixed frame size",
        "Frame size value",
        "Increased frame size",
        "Min frame size",
        "Max frame size",
        "Emixed frame size",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Frame size value",
        "Packet rate",
        "Rate value",
        CTC_CLI_VLAN_DESC,
        CTC_CLI_VLAN_RANGE_DESC,
        "Cvlan domain",
        "Transmit mode",
        "Continuous",
        "Packet number",
        "Number value",
        "Transmit period",
        "Period value",
        "Pattern type",
        "Repeat mode",
        "Repeat value",
        "Random mode",
        "Increase by byte mode",
        "Decrease by byte mode",
        "Increase by word mode",
        "Decrease by word mode",
        "Timeout",
        "Time value",
        "Burst enable",
        "Burst count",
        "Inter burst gap",
        "IBG value",
        "Timestamp enable",
        "Timestamp offset",
        "Timestamp in tunnel enable",
        "Sequence enable",
        "Sequence offset",
        "update checksum",
        "Checksum offset",
        "Inter packet gap",
        "IPG value",
        "Iloop",
        "Vrf id",
        "Vrf id value",
        "DM stats mode",
        "Far end dm stats mode",
        "Near end dm stats mode",
        "Timestamp format use NTP",
        "Light mode enable",
        "Ses rate threshold",
        "Value",
        "Continuous seconds count to judge available/unavailable period",
        "Value",
        "Color of the packet",
        "Refer to ctc_qos_color_t",
        "Priority of the packet",
        "Priority value",
        "OAM type",
        "Value")
{
    int32 ret = 0;
    uint8 index = 0;
    uint8 temp = 0;
    uint8 i = 0;
    uint8 count = 0;
    ctc_npm_cfg_t cfg;
    static char file[256] = {0};
    uint8 pkt_buf[CTC_NPM_MAX_PKTHDR_LEN] = {0};
    uint32 header_len = 0;
    static uint8 lbm_pkthd[64] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x60, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };
    static uint8 tst_pkthd[64] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x60, 0x25, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1e, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };

    static uint8 slm_pkthd[80] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x60, 0x37, 0x00, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };

#if 0
    static uint8 slm_pkthd[80] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x60, 0x37, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    };
#endif
    static uint8 onesl_pkthd[64] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x60, 0x35, 0x00, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };


    static uint8 onedm_pkthd[64] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x61, 0x2d, 0x00, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };


    static uint8 dmm_pkthd[64] =
    {
        0x01, 0x80, 0xC2, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x02,
        0x89, 0x02, 0x61, 0x2f, 0x00, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };


    sal_memset(&cfg, 0, sizeof(ctc_npm_cfg_t));

    CTC_CLI_GET_UINT8_RANGE("session id", cfg.session_id, argv[0], 0, CTC_MAX_UINT8_VALUE);
    index = CTC_CLI_GET_ARGC_INDEX("dest-gport");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32_RANGE("dest gport", cfg.dest_gport, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("nh-id");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32_RANGE("nexthop id", cfg.nh_id, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
        cfg.flag |= CTC_NPM_CFG_FLAG_NHID_VALID;
    }

    index = CTC_CLI_GET_ARGC_INDEX("is-mcast");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_MCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-lbm");
    if (0xFF != index)
    {
        cfg.pkt_format.pkt_header = (void*)lbm_pkthd;
        cfg.pkt_format.header_len = 27;
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-tst");
    if (0xFF != index)
    {
        cfg.pkt_format.pkt_header = (void*)tst_pkthd;
        cfg.pkt_format.header_len = 30;
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-slm");
    if (0xFF != index)
    {
        cfg.pkt_format.pkt_header = (void*)slm_pkthd;
        cfg.pkt_format.header_len = 74;
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-1sl");
    if (0xFF != index)
    {
        cfg.pkt_format.pkt_header = (void*)onesl_pkthd;
        cfg.pkt_format.header_len = 39;
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-dmm");
    if (0xFF != index)
    {
        cfg.pkt_format.pkt_header = (void*)dmm_pkthd;
        cfg.pkt_format.header_len = 55;
        cfg.flag |= CTC_NPM_CFG_FLAG_DMR_NOT_TO_CPU;
    }

    index = CTC_CLI_GET_ARGC_INDEX("eth-1dm");
    if (0xFF != index)
    {
        cfg.pkt_format.pkt_header = (void*)onedm_pkthd;
        cfg.pkt_format.header_len = 31;
    }


    sal_memset(pkt_buf, 0, CTC_NPM_MAX_PKTHDR_LEN);

    index = CTC_CLI_GET_ARGC_INDEX("pkt-file");
    if (0xFF != index)
    {
        /* get packet from file */
        sal_strncpy((char*)file, argv[index + 1], CTC_MAX_ARRAY_LEN(file));
        /* get packet from file */
        ret = _npm_cli_packet_get_from_file(vty, file, pkt_buf, &header_len);

        if (CLI_ERROR == ret)
        {
            return CLI_ERROR;
        }

        cfg.pkt_format.pkt_header = (void*)pkt_buf;
        cfg.pkt_format.header_len = header_len;
    }


    index = CTC_CLI_GET_ARGC_INDEX("fixed");
    if (0xFF != index)
    {
        cfg.pkt_format.frame_size_mode = 0;
        CTC_CLI_GET_UINT32_RANGE("frame size", cfg.pkt_format.frame_size, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
        temp = index + 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("increased");
    if (0xFF != index)
    {
        cfg.pkt_format.frame_size_mode = 1;
        CTC_CLI_GET_UINT32_RANGE("min frame size", cfg.pkt_format.min_frame_size, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
        CTC_CLI_GET_UINT32_RANGE("max frame size", cfg.pkt_format.frame_size, argv[index + 2], 0, CTC_MAX_UINT32_VALUE);
        temp = index + 2;
    }

    index = CTC_CLI_GET_ARGC_INDEX("emixed");
    if (0xFF != index)
    {
        cfg.pkt_format.frame_size_mode = 2;
        for (i = 0; i < CTC_NPM_MAX_EMIX_NUM; i++)
        {
            CTC_CLI_GET_UINT16_RANGE("emix size array", cfg.pkt_format.emix_size[i], argv[index + 1 + i], 0, CTC_MAX_UINT16_VALUE);
            if (cfg.pkt_format.emix_size[i] != 0)
            {
                count = count + 1;
            }

        }
        cfg.pkt_format.emix_size_num = count;
        temp = index + 16;
    }

    CTC_CLI_GET_UINT32_RANGE("transmit rate", cfg.rate, argv[temp + 1], 0, CTC_MAX_UINT32_VALUE);

    index = CTC_CLI_GET_ARGC_INDEX("vlan-id");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE("vlan id", cfg.vlan_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("cvlan-domain");
    if (0xFF != index)
    {
        cfg.vlan_domain = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("continuous");
    if (0xFF != index)
    {
        cfg.tx_mode = 0;
    }
    index = CTC_CLI_GET_ARGC_INDEX("pkt-num");
    if (0xFF != index)
    {
        cfg.tx_mode = 1;
        CTC_CLI_GET_UINT32_RANGE("packet number", cfg.packet_num, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("tx-period");
    if (0xFF != index)
    {
        cfg.tx_mode = 2;
        CTC_CLI_GET_UINT32_RANGE("transmit period", cfg.tx_period, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }



    index = CTC_CLI_GET_ARGC_INDEX("repeat");
    if (0xFF != index)
    {
        cfg.pkt_format.pattern_type = 0;
        CTC_CLI_GET_UINT32_RANGE("repeat pattern value", cfg.pkt_format.repeat_pattern, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("random");
    if (0xFF != index)
    {
        cfg.pkt_format.pattern_type = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("increase-by-byte");
    if (0xFF != index)
    {
        cfg.pkt_format.pattern_type = 2;
    }

    index = CTC_CLI_GET_ARGC_INDEX("decrease-by-byte");
    if (0xFF != index)
    {
        cfg.pkt_format.pattern_type = 3;
    }

    index = CTC_CLI_GET_ARGC_INDEX("increase-by-word");
    if (0xFF != index)
    {
        cfg.pkt_format.pattern_type = 4;
    }

    index = CTC_CLI_GET_ARGC_INDEX("decrease-by-word");
    if (0xFF != index)
    {
        cfg.pkt_format.pattern_type = 5;
    }

    index = CTC_CLI_GET_ARGC_INDEX("timeout");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT8_RANGE("timeout", cfg.timeout, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("burst-en");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_BURST_EN;
        CTC_CLI_GET_UINT32_RANGE("burst count", cfg.burst_cnt, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("ibg");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32_RANGE("inter burst gap", cfg.ibg, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("ts-en");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_TS_EN;
        CTC_CLI_GET_UINT16_RANGE("timestamp offset", cfg.pkt_format.ts_offset, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
    }
    index = CTC_CLI_GET_ARGC_INDEX("tunnel-pkt");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_TUNNEL_PKT;
    }
    index = CTC_CLI_GET_ARGC_INDEX("chksum-offset");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE("checksum offset", cfg.pkt_format.chksum_offset, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
    }
        
    index = CTC_CLI_GET_ARGC_INDEX("seq-en");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_SEQ_EN;
        CTC_CLI_GET_UINT8_RANGE("sequence offset", cfg.pkt_format.seq_num_offset, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    cfg.pkt_format.ipg = 20;
    index = CTC_CLI_GET_ARGC_INDEX("ipg");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT8_RANGE("inter packet gap", cfg.pkt_format.ipg, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("iloop");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_ILOOP;
    }

    index = CTC_CLI_GET_ARGC_INDEX("far");
    if (0xFF != index)
    {
        cfg.dm_stats_mode= 1;
    }
    index = CTC_CLI_GET_ARGC_INDEX("near");
    if (0xFF != index)
    {
        cfg.dm_stats_mode = 2;
    }

    index = CTC_CLI_GET_ARGC_INDEX("is-ntp-ts");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_NTP_TS;
    }
    index = CTC_CLI_GET_ARGC_INDEX("light-mode-en");
    if (0xFF != index)
    {
        cfg.lite_cfg.mode= 2;
    }
    index = CTC_CLI_GET_ARGC_INDEX("ses-thrd");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_FLR_FOR_SES;
        CTC_CLI_GET_UINT8_RANGE("ses-thrd", cfg.flr_for_ses, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("con-period");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_AVL_PERIOD_THRD;
        CTC_CLI_GET_UINT32_RANGE("con-period", cfg.avl_period_thrd, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }
    index = CTC_CLI_GET_ARGC_INDEX("vrf-id");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_VRF_EN;
        CTC_CLI_GET_UINT8_RANGE("vrf id", cfg.vrf_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
    }    
    index = CTC_CLI_GET_ARGC_INDEX("color");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_COLOR;
        CTC_CLI_GET_UINT8_RANGE("color", cfg.pkt_format.color, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("priority");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_PRIORITY;
        CTC_CLI_GET_UINT8_RANGE("priority", cfg.pkt_format.priority, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }
    index = CTC_CLI_GET_ARGC_INDEX("oam-type");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT8_RANGE("oam type", cfg.oam_type, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    if(g_ctcs_api_en)
    {
        ret = ctcs_npm_set_config(g_api_ldev, &cfg);
    }
    else
    {
        ret = ctc_npm_set_config(g_api_ldev, &cfg);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    if (cfg.session_id <= 31)
    {
        tx_rate[cfg.session_id] = (float)cfg.rate *1000;   /*bps*/
        g_ipg[cfg.session_id] = cfg.pkt_format.ipg;
    }
    else
    {
        ctc_cli_out("Invalid npm session id\n");
        return CLI_ERROR;
    }

    return CLI_SUCCESS;


}


CTC_CLI(ctc_cli_npm_lite_set_cfg,
        ctc_cli_npm_lite_set_cfg_cmd,
        "npm session SESSION cfg (twamp-lite{is-ntp-ts|mode MODE |iloop |offset-adjust-en |vrf-id VRF_ID |frame-size FRAME_SIZE |src-udp-port SRC_PORT|dst-udp-port DST_PORT | (dest-gport GPORT| nhid NHID ) |(ipv4-sa A.B.C.D (ipv4-da A.B.C.D|) | ipv6-sa X:X::X:X ipv6-da X:X::X:X)|}|dmm-lite(is-1dm|)){rate RATE |dm-stats-mode (far|near|two-way)|tx-mode (continuous | pkt-num NUM)|tx-cos COS|}(lmep-index IDX|)(enable|disable)",
CTC_CLI_NPM_M_STR,
        "Session id",
        "Value",
        "Config",
        "twamp lite mode",
        "Timestamp format use NTP",
        "sender/reflecter/light mode",
        "0: Session-sender, 1:Session-reflecter full mode, 2:Session-reflecter light mode",
        "Iloop, not bypass ipe",
        "Packet offset adjust enable used for twamp reflector l3vpn after acl offset",
        "Vrf id",
        "Vrf id value",
        "Frame size",
        "Value",
        "UDP source port",
        "Value",
        "UDP dest port",
        "Value",
        "Dest gport",
        "Dest gport value",
        "NextHop ID",
        "Value",
        "IPv4 sa",
        CTC_CLI_IPV4_FORMAT,
        "IPv4 da",
        CTC_CLI_IPV4_FORMAT,
        "IPv6 sa",
        CTC_CLI_IPV6_FORMAT,
        "IPv6 da",
        CTC_CLI_IPV6_FORMAT,
        "DMM lite mode",
        "Is 1dm",
        "Send packets rate",
        "Value",
        "DM stats mode",
        "Far end delay/jitter measure",
        "Near end delay/jitter measure",
        "Two way delay/jitter measure",
        "Transmit mode",
        "Continuous",
        "Packet number",
        "Number",
        "Set tx cos",
        CTC_CLI_COS_RANGE_DESC,
        "Local MEP index allocated by system",
        "Value",
        "Enable",
        "Disable")
{
    int32 ret = 0;
    uint8 index = 0;
    ctc_npm_cfg_t cfg;
    ipv6_addr_t ipv6_address;
    sal_memset(&cfg, 0, sizeof(ctc_npm_cfg_t));
    CTC_CLI_GET_UINT32_RANGE("session id", cfg.session_id, argv[0], 0, CTC_MAX_UINT32_VALUE);
    cfg.session_id  |= (CTC_NPM_SESSION_TYPE_LITE<<CTC_NPM_SESSION_ID_LEN);
    index = CTC_CLI_GET_ARGC_INDEX("twamp-lite");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_TWAMP_LITE;
        index = CTC_CLI_GET_ARGC_INDEX("is-ntp-ts");
        if (0xFF != index)
        {
            cfg.flag |= CTC_NPM_CFG_FLAG_NTP_TS;
        }
        index = CTC_CLI_GET_ARGC_INDEX("mode");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT8_RANGE("mode", cfg.lite_cfg.mode, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
        }
        index = CTC_CLI_GET_ARGC_INDEX("iloop");
        if (0xFF != index)
        {
            cfg.flag |= CTC_NPM_CFG_FLAG_ILOOP;
        }
        index = CTC_CLI_GET_ARGC_INDEX("offset-adjust-en");
        if (0xFF != index)
        {
            cfg.flag |= CTC_NPM_CFG_FLAG_OFFSET_ADJ;
        }
        index = CTC_CLI_GET_ARGC_INDEX("vrf-id");
        if (0xFF != index)
        {
            cfg.flag |= CTC_NPM_CFG_FLAG_VRF_EN;
            CTC_CLI_GET_UINT8_RANGE("vrf id", cfg.vrf_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        }
        index = CTC_CLI_GET_ARGC_INDEX("src-udp-port");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT16_RANGE("UDP source Port", cfg.lite_cfg.src_port, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        }
        index = CTC_CLI_GET_ARGC_INDEX("dst-udp-port");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT16_RANGE("UDP dest Port", cfg.lite_cfg.dst_port, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        }
        
        index = CTC_CLI_GET_ARGC_INDEX("dest-gport");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT32_RANGE("dest gport", cfg.dest_gport, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
        }

        index = CTC_CLI_GET_ARGC_INDEX("nhid");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT32_RANGE("Nhid", cfg.lite_cfg.nhid, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
        }

        index = CTC_CLI_GET_ARGC_INDEX("ipv4-sa");
        if (0xFF != index)
        {
            CTC_CLI_GET_IPV4_ADDRESS("IPv4-sa", cfg.lite_cfg.ip4_sa, argv[index + 1]);
        }

        index = CTC_CLI_GET_ARGC_INDEX("ipv4-da");
        if (0xFF != index)
        {
            CTC_CLI_GET_IPV4_ADDRESS("IPv4-da", cfg.lite_cfg.ip4_da, argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX("ipv6-sa");
        if (0xFF != index)
        {
            cfg.lite_cfg.is_ipv6 =1;
            CTC_CLI_GET_IPV6_ADDRESS("ipv6-sa", ipv6_address, argv[index + 1]);
            /* adjust endian */
            cfg.lite_cfg.ipv6_sa[0] = sal_htonl(ipv6_address[0]);
            cfg.lite_cfg.ipv6_sa[1] = sal_htonl(ipv6_address[1]);
            cfg.lite_cfg.ipv6_sa[2] = sal_htonl(ipv6_address[2]);
            cfg.lite_cfg.ipv6_sa[3] = sal_htonl(ipv6_address[3]);
        }

        index = CTC_CLI_GET_ARGC_INDEX("ipv6-da");
        if (0xFF != index)
        {
            cfg.lite_cfg.is_ipv6 = 1;
            CTC_CLI_GET_IPV6_ADDRESS("ipv6-da", ipv6_address, argv[index + 1]);
            /* adjust endian */
            cfg.lite_cfg.ipv6_da[0] = sal_htonl(ipv6_address[0]);
            cfg.lite_cfg.ipv6_da[1] = sal_htonl(ipv6_address[1]);
            cfg.lite_cfg.ipv6_da[2] = sal_htonl(ipv6_address[2]);
            cfg.lite_cfg.ipv6_da[3] = sal_htonl(ipv6_address[3]);
        }
    }
    index = CTC_CLI_GET_ARGC_INDEX("dmm-lite");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_DMM_LITE;
        index = CTC_CLI_GET_ARGC_INDEX("is-1dm");
        if (0xFF != index)
        {
            cfg.lite_cfg.dm_tx_type =1;
        }
    }
    index = CTC_CLI_GET_ARGC_INDEX("rate");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE(" rate", cfg.rate, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
    }
    index = CTC_CLI_GET_ARGC_INDEX("far");
    if (0xFF != index)
    {
        cfg.dm_stats_mode= CTC_NPM_MEASURE_MODE_FAR_END;
    }
    index = CTC_CLI_GET_ARGC_INDEX("near");
    if (0xFF != index)
    {
        cfg.dm_stats_mode = CTC_NPM_MEASURE_MODE_NEAR_END;
    }
    index = CTC_CLI_GET_ARGC_INDEX("two-way");
    if (0xFF != index)
    {
        cfg.dm_stats_mode = CTC_NPM_MEASURE_MODE_TWO_WAY;
    }
	index = CTC_CLI_GET_ARGC_INDEX("continuous");
    if (0xFF != index)
    {
        cfg.tx_mode = 0;
    }
    index = CTC_CLI_GET_ARGC_INDEX("pkt-num");
    if (0xFF != index)
    {
        cfg.tx_mode = 1;
        CTC_CLI_GET_UINT32_RANGE("packet number", cfg.packet_num, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }
    index = CTC_CLI_GET_ARGC_INDEX("tx-cos");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT8_RANGE("Tx Cos", cfg.lite_cfg.tx_cos_exp, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }
	index = CTC_CLI_GET_ARGC_INDEX("frame-size");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32_RANGE("Frame Size", cfg.pkt_format.frame_size, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }
    /*sys mep index*/
    index = CTC_CLI_GET_ARGC_INDEX("lmep-index");
    if (index != 0xFF)
    {
        CTC_CLI_GET_UINT32_RANGE("lmep-index", cfg.lite_cfg.lmep_index, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
    }
    index = CTC_CLI_GET_ARGC_INDEX("enable");
    if (0xFF != index)
    {
        cfg.lite_cfg.enable =1;
    }
    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_set_config(g_api_ldev, &cfg);
    }
    else
    {
        ret = ctc_npm_set_config(g_api_ldev, &cfg);
    }
    if (cfg.lite_cfg.enable)
    {
        ctc_cli_out("Local mep_index is %d\n", cfg.lite_cfg.lmep_index);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;

}
CTC_CLI(ctc_cli_npm_show_sample_cache,
        ctc_cli_npm_show_sample_cache_cmd,
        "show npm sample cache",
        CTC_CLI_SHOW_STR,
        CTC_CLI_NPM_M_STR,
        "Sample",
        "Cache")
{
    uint8 loop = 0;
    uint32 session_id = 0;
    char  rx_rate_str[64] = {0};
    CTC_CLI_NPM_CAHCE_INIT(CLI_ERROR);
    session_id = sample_cache[0].session_id;

    ctc_cli_out("-------------------------NPM Sample Cache----------------------------------------\n");
    ctc_cli_out("Tx-rate:Transmit rate\n");
    ctc_cli_out("Rx-rate:Receive Rate\n");
    ctc_cli_out("FTD:Frame Transfer Delay(unit:ns)\n");
    ctc_cli_out("Tx-en:Autogen transmit pkts enable\n");
    ctc_cli_out("Tx-pkts:Autogen transmit pkts number\n");
    ctc_cli_out("Rx-pkts:Autogen receive pkts number\n");
    ctc_cli_out("----------------------------------------------------------------------------------\n");
    if (sample_cache[0].valid)
    {
        ctc_cli_out("%-15s: %u\n", "session id", session_id);
    }
    else
    {
        ctc_cli_out("%-15s: %s\n", "session id", "N/A");
    }
    ctc_cli_out("%-15s: %d\n", "interval", sample_cache[0].interval);
    ctc_cli_out("%-15s: %d\n", "total num", sample_cache[0].num);
    ctc_cli_out("%-15s: %s\n", "Tx-en", sample_cache[0].tx_en?"Y":"N");
    if (tx_rate[session_id] > 1000*1000)
    {
        ctc_cli_out("%-15s: %.2lf\n", "Tx-rate(Mbps)", tx_rate[session_id]/1000/1000);
    }
    else if(tx_rate[session_id] > 1000)
    {
        ctc_cli_out("%-15s: %.2lf\n", "Tx-rate(Kbps)", tx_rate[session_id]/1000);
    }
    else
    {
        ctc_cli_out("%-15s: %.2lf\n", "Tx-rate(bps)", tx_rate[session_id]);
    }

    ctc_cli_out("----------------------------------------------------------------------------------\n");
    ctc_cli_out("%-10s%-15s%-10s%-10s%-10s\n", "NO.", "Rx-rate", "FTD", "Tx-pkts", "Rx-pkts");
    ctc_cli_out("----------------------------------------------------------------------------------\n");

    if (sample_cache[loop].ir_local > 1000*1000)
    {
        sal_sprintf(rx_rate_str, "%.2f(Mbps)", sample_cache[loop].ir_local / 1000 / 1000);
    }
    else if(sample_cache[loop].ir_local > 1000)
    {
        sal_sprintf(rx_rate_str, "%.2f(Kbps)", sample_cache[loop].ir_local / 1000);
    }
    else
    {
        sal_sprintf(rx_rate_str, "%.2f(bps)", sample_cache[loop].ir_local);
    }

    for (loop = 0; loop < 255; loop++)
    {
        if (sample_cache[loop].valid)
        {
            ctc_cli_out("%-10d%-15s%-10"PRIu64"%-10"PRIu64"%-10"PRIu64"\n", sample_cache[loop].local_count, rx_rate_str,
                        sample_cache[loop].fd_local, sample_cache[loop].tx_pkts, sample_cache[loop].rx_pkts);
        }
    }

    return CLI_SUCCESS;
}
#endif


CTC_CLI(ctc_cli_npm_set_cfg_rx,
        ctc_cli_npm_set_cfg_rx_cmd,
        "npm session SESSION cfg rx (enable {ts-en TSOFFSET|seq-en SEQOFFSET | dm-stats-mode (far|near)}| disable)",
        CTC_CLI_NPM_M_STR,
        "Session id",
        "Value",
        "Config",
        "Rx role",
        "Enable",
        "Timestamp enable",
        "Timestamp offset",
        "Sequence enable",
        "Sequence offset",
        "DM stats mode",
        "Far end dm stats mode",
        "Near end dm stats mode",
        "Disable")
{
    int32 ret = 0;
    uint8 index = 0;
    ctc_npm_cfg_t cfg;
    sal_memset(&cfg, 0, sizeof(ctc_npm_cfg_t));

    CTC_CLI_GET_UINT8_RANGE("session id", cfg.session_id, argv[0], 0, CTC_MAX_UINT8_VALUE);
    cfg.flag |= CTC_NPM_CFG_FLAG_RX_ROLE_EN;

    index = CTC_CLI_GET_ARGC_INDEX("enable");
    if (0xFF != index)
    {
        cfg.rx_role_en = 1;
    }

    index = CTC_CLI_GET_ARGC_INDEX("disable");
    if (0xFF != index)
    {
        cfg.rx_role_en = 0;
    }

    index = CTC_CLI_GET_ARGC_INDEX("ts-en");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_TS_EN;
        CTC_CLI_GET_UINT16_RANGE("timestamp offset", cfg.pkt_format.ts_offset, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
    }

    index = CTC_CLI_GET_ARGC_INDEX("far");
    if (0xFF != index)
    {
        cfg.dm_stats_mode= 1;
    }
    index = CTC_CLI_GET_ARGC_INDEX("near");
    if (0xFF != index)
    {
        cfg.dm_stats_mode = 2;
    }

    index = CTC_CLI_GET_ARGC_INDEX("seq-en");
    if (0xFF != index)
    {
        cfg.flag |= CTC_NPM_CFG_FLAG_SEQ_EN;
        CTC_CLI_GET_UINT8_RANGE("sequence offset", cfg.pkt_format.seq_num_offset, argv[index + 1], 0, CTC_MAX_UINT8_VALUE);
    }

    if(g_ctcs_api_en)
    {
        ret = ctcs_npm_set_config(g_api_ldev, &cfg);
    }
    else
    {
        ret = ctc_npm_set_config(g_api_ldev, &cfg);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_npm_init_deinit,
	ctc_cli_npm_init_deinit_cmd,
	"npm (init|deinit) ",
	CTC_CLI_NPM_M_STR,
	"Init",
	"Deinit")
{
	uint32 index = 0xFF;
	int32 ret = CLI_ERROR;
	index = CTC_CLI_GET_ARGC_INDEX("deinit");
	if (0xFF != index)
	{
		if (g_ctcs_api_en)
		{
			ret = ctcs_npm_deinit(g_api_ldev);
		}
		else
		{
			ret = ctc_npm_deinit();
		}
	}
	else
	{
		if (g_ctcs_api_en)
		{
			ret = ctcs_npm_init(g_api_ldev, NULL);
		}
		else
		{
			ret = ctc_npm_init(NULL);
		}
	}

	if (ret)
	{
		ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
		return CLI_ERROR;
	}
	return CLI_SUCCESS;
}
CTC_CLI(ctc_cli_npm_create_im_flow,
        ctc_cli_npm_create_im_flow_cmd,
        "npm create im-flow flow-id FLOW_ID flow-type (source|transit|sink) im-type (mpls-ioam \
        {loss-prof-id VALUE | fih-type VALUE}) (stats-id VALUE)",
        CTC_CLI_NPM_M_STR,
        "Create action",
        "In-Band Measurement Flow", 
        "Flow Id",
        "Flow ID",
        "Flow type",
        "Source Node",
        "Transmit Node",
        "Sink Node",
        "Im type",
        "Ipv4 ioam",
        "Ipv6 ioam",
        "Mpls ioam",
        "Loss profile id,<1-7>",
        "VALUE",
        "FIH type",
        "FIH type: 0x00,0x01,0x02",
        "VXLAN",
        "Stats id",
        "VALUE")
{
    uint8 index = 0;
    int32 ret = CLI_SUCCESS;
    ctc_npm_im_flow_t im_flow;

    sal_memset(&im_flow, 0, sizeof(ctc_npm_im_flow_t));

    CTC_CLI_GET_UINT32_RANGE("flow id", im_flow.flow_id, argv[0], 0, CTC_MAX_UINT32_VALUE);

    index = CTC_CLI_GET_ARGC_INDEX("source");
    if (0xFF != index)
    {
        im_flow.flow_type = CTC_NPM_IM_FLOW_TYPE_SOURCE;
    }

    index = CTC_CLI_GET_ARGC_INDEX("transit");
    if (0xFF != index)
    {
        im_flow.flow_type = CTC_NPM_IM_FLOW_TYPE_TRANSIT;
    }

    index = CTC_CLI_GET_ARGC_INDEX("sink");
    if (0xFF != index)
    {
        im_flow.flow_type = CTC_NPM_IM_FLOW_TYPE_SINK;
    }

    index = CTC_CLI_GET_ARGC_INDEX("mpls-ioam");
    if (0xFF != index)
    {
        im_flow.type = CTC_NPM_IM_TYPE_MPLS;

        index = CTC_CLI_GET_ARGC_INDEX("loss-prof-id");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT8("loss-prof-id", im_flow.loss_prof_id, argv[index + 1]);
        }
        index = CTC_CLI_GET_ARGC_INDEX("fih-type");
        if (0xFF != index)
        {
            CTC_CLI_GET_UINT8("fih-type", im_flow.fih_type, argv[index + 1]);
        }
    }

    index = CTC_CLI_GET_ARGC_INDEX("stats-id");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32("stats-id", im_flow.stats_id, argv[index + 1]);
    }
    //CTC_CLI_GET_UINT32_RANGE("stats id", im_flow.stats_id, argv[3], 0, CTC_MAX_UINT32_VALUE);

    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_create_im_flow(g_api_ldev, &im_flow);
    }
    else
    {
        ret = ctc_npm_create_im_flow(&im_flow);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_npm_destroy_im_flow,
        ctc_cli_npm_destroy_im_flow_cmd,
        "npm destroy im-flow flow-id FLOWID",
        CTC_CLI_NPM_M_STR,
        "Destroy action",
        "In-Band Measurement Flow",
        "Flow Id",
        "Flow ID")
{
    int32 ret = CLI_SUCCESS;
    uint32 flow_id = 0;

    CTC_CLI_GET_UINT32_RANGE("flow-id", flow_id, argv[0], 0, CTC_MAX_UINT32_VALUE);

    if (g_ctcs_api_en)
    {
        ret = ctcs_npm_destory_im_flow(g_api_ldev, flow_id);
    }
    else
    {
        ret = ctc_npm_destory_im_flow(flow_id);
    }

    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }
    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_npm_set_im_flow_property,
        ctc_cli_npm_set_im_flow_property_cmd,
        "npm im-flow flow-id FLOWID property (loss VALUE |delay VALUE |delay-interval VALUE) \
        {"CTC_CLI_PP_BMP" |}",
        CTC_CLI_NPM_M_STR,
        "In-Band Measurement Flow",
        "Flow Id",
        "FlOW ID",
        "Set im flow property",
        "Loss Measurement",
        "VALUE",
        "Delay Measurement",
        "VALUE",
        "Delay Measurement interval set hardware color mode",
        "VALUE",
        CTC_CLI_PP_BMP_DESC)
{
    uint8 index = 0;
    int32 ret = CLI_SUCCESS;
    uint32 value = 0;
    ctc_npm_im_flow_property_t im_flow_property;

    sal_memset(&im_flow_property, 0, sizeof(ctc_npm_im_flow_property_t));
    im_flow_property.value = &value;

    CTC_CLI_GET_UINT32_RANGE("flow-id", im_flow_property.flow_id, argv[0], 0, CTC_MAX_UINT32_VALUE);

    index = CTC_CLI_GET_ARGC_INDEX("loss");
    if (0xFF != index)
    {
        im_flow_property.property_type= CTC_NPM_IM_FLOW_PROP_LOSS;
        CTC_CLI_GET_UINT32("loss", value, argv[index + 1]);
    }

    index = CTC_CLI_GET_ARGC_INDEX("delay");
    if (0xFF != index)
    {
        im_flow_property.property_type = CTC_NPM_IM_FLOW_PROP_DELAY;
        CTC_CLI_GET_UINT32("delay", value, argv[index + 1]);
    }
    index = CTC_CLI_GET_ARGC_INDEX("delay-interval");
    if (0xFF != index)
    {
        im_flow_property.property_type = CTC_NPM_IM_FLOW_PROP_DELAY_INTERVAL;
        CTC_CLI_GET_UINT32("delay interval", value, argv[index + 1]);
    }

    if(g_ctcs_api_en)
    {
        ret = ctcs_npm_set_im_flow_property(g_api_ldev, &im_flow_property);
    }
    else
    {
        ret = ctc_npm_set_im_flow_property(&im_flow_property);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_npm_show_im_flow_property,
        ctc_cli_npm_show_im_flow_property_cmd,
        "show npm im-flow flow-id FLOWID property (loss |delay |delay-interval )",
        CTC_CLI_SHOW_STR,
        CTC_CLI_NPM_M_STR,
        "In-Band Measurement Flow",
        "Flow Id",
        "FlOW ID",
        "Im flow property",
        "Loss Measurement",
        "Delay Measurement",
        "Delay Measurement interval in hardware color mode")
{
    uint8 index = 0;
    int32 ret = CLI_SUCCESS;
    uint32 value = 0;
    ctc_npm_im_flow_property_t im_flow_property;

    sal_memset(&im_flow_property, 0, sizeof(ctc_npm_im_flow_property_t));
    im_flow_property.value = &value;

    CTC_CLI_GET_UINT32_RANGE("flow-id", im_flow_property.flow_id, argv[0], 0, CTC_MAX_UINT32_VALUE);

    index = CTC_CLI_GET_ARGC_INDEX("loss");
    if (0xFF != index)
    {
        im_flow_property.property_type= CTC_NPM_IM_FLOW_PROP_LOSS;
    }

    index = CTC_CLI_GET_ARGC_INDEX("delay");
    if (0xFF != index)
    {
        im_flow_property.property_type = CTC_NPM_IM_FLOW_PROP_DELAY;
    }

    index = CTC_CLI_GET_ARGC_INDEX("delay-interval");
    if (0xFF != index)
    {
        im_flow_property.property_type = CTC_NPM_IM_FLOW_PROP_DELAY_INTERVAL;
    }

    if(g_ctcs_api_en)
    {
        ret = ctcs_npm_get_im_flow_property(g_api_ldev, &im_flow_property);
    }
    else
    {
        ret = ctc_npm_get_im_flow_property(&im_flow_property);
    }
    if (ret < 0)
    {
        ctc_cli_out("%% %s \n\r", ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    switch(im_flow_property.property_type)
    {
    case CTC_NPM_IM_FLOW_PROP_LOSS:
        ctc_cli_out("%-30s:%-6u \n", "Loss Property", value);
        break;
    case CTC_NPM_IM_FLOW_PROP_DELAY:
        ctc_cli_out("%-30s:%-6u \n", "Delay Property", value);
        break;
    case CTC_NPM_IM_FLOW_PROP_DELAY_INTERVAL:
        ctc_cli_out("%-30s:%-6u \n", "Delay Interval", value);
        break;
    default:
        break;
    }

    return CLI_SUCCESS;
}

    
int32
ctc_npm_cli_init(void)
{
    install_element(CTC_SDK_MODE, &ctc_cli_npm_set_session_transmit_en_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_clear_session_stats_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_set_global_cfg_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_show_global_cfg_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_debug_on_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_debug_off_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_init_deinit_cmd);

#if defined(SDK_IN_USERMODE)
    install_element(CTC_SDK_MODE, &ctc_cli_npm_show_session_stats_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_set_cfg_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_lite_set_cfg_cmd);
    install_element(CTC_SDK_MODE, &ctc_cli_npm_set_cfg_rx_cmd);

    install_element(CTC_SDK_MODE, &ctc_cli_npm_show_sample_cache_cmd);
#endif

    install_element(CTC_SDK_MODE,  &ctc_cli_npm_create_im_flow_cmd);
    install_element(CTC_SDK_MODE,  &ctc_cli_npm_destroy_im_flow_cmd);
    install_element(CTC_SDK_MODE,  &ctc_cli_npm_set_im_flow_property_cmd);
    install_element(CTC_SDK_MODE,  &ctc_cli_npm_show_im_flow_property_cmd);

    return CLI_SUCCESS;
}


#endif

